package com.insight.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuanqiao.insight.common.constant.CommonConstant;
import com.insight.common.util.IPUtils;
import com.insight.common.util.SpringContextUtils;
import com.insight.common.util.oConvertUtils;
import com.insight.modules.system.entity.SysRolePermission;
import com.insight.modules.system.mapper.SysRolePermissionMapper;
import com.insight.modules.system.service.ISysRolePermissionService;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * <p>
 * 角色权限表 服务实现类
 * </p>
 *
 * @Author scott
 * @since 2018-12-21
 */
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * SysRolePermissionServiceImpl 是角色权限关系的业务实现类
 * 主要负责角色与权限之间的分配、更新和删除操作
 */
@Service
public class SysRolePermissionServiceImpl extends ServiceImpl<SysRolePermissionMapper, SysRolePermission> implements ISysRolePermissionService {

	/**
	 * 保存角色权限信息（先清除已有权限，再重新保存）
	 * @param roleId 角色ID
	 * @param permissionIds 权限ID集合（逗号分隔）
	 */
	@Override
	public void saveRolePermission(String roleId, String permissionIds) {
		String ip = CommonConstant.LOCAL_IP;

		// 获取当前 HTTP 请求对象
		HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
		// 获取请求来源 IP 地址
		ip = IPUtils.getIpAddr(request);

		// 构造条件删除已有的该角色权限
		LambdaQueryWrapper<SysRolePermission> query = new QueryWrapper<SysRolePermission>()
				.lambda().eq(SysRolePermission::getRoleId, roleId);
		this.remove(query);

		// 新权限列表
		List<SysRolePermission> list = new ArrayList<>();
		String[] arr = permissionIds.split(",");
		for (String p : arr) {
			if (oConvertUtils.isNotEmpty(p)) {
				// 构造新的权限关系对象
				SysRolePermission rolepms = new SysRolePermission(roleId, p);
				rolepms.setOperateDate(new Date());  // 设置操作时间
				rolepms.setOperateIp(ip);            // 设置操作 IP
				list.add(rolepms);
			}
		}

		// 批量保存新的角色权限
		this.saveBatch(list);
	}

	/**
	 * 更新角色权限信息（计算增量和差量）
	 * @param roleId 角色ID
	 * @param permissionIds 当前权限集合（逗号分隔）
	 * @param lastPermissionIds 上一次保存的权限集合（逗号分隔）
	 */
	@Override
	public void saveRolePermission(String roleId, String permissionIds, String lastPermissionIds) {
		String ip = CommonConstant.LOCAL_IP;
		HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
		ip = IPUtils.getIpAddr(request);


		// 获取需要新增的权限ID
		List<String> add = getDiff(lastPermissionIds, permissionIds);
		if (add != null && add.size() > 0) {
			List<SysRolePermission> list = new ArrayList<>();
			for (String p : add) {
				if (oConvertUtils.isNotEmpty(p)) {
					SysRolePermission rolepms = new SysRolePermission(roleId, p);
					rolepms.setOperateDate(new Date());
					rolepms.setOperateIp(ip);
					list.add(rolepms);
				}
			}
			this.saveBatch(list);
		}

		// 获取需要删除的权限ID
		List<String> delete = getDiff(permissionIds, lastPermissionIds);
		if (delete != null && delete.size() > 0) {
			for (String permissionId : delete) {
				this.remove(new QueryWrapper<SysRolePermission>()
						.lambda()
						.eq(SysRolePermission::getRoleId, roleId)
						.eq(SysRolePermission::getPermissionId, permissionId));
			}
		}
	}

	/**
	 * 获取在 diff 中存在但 main 中不存在的差异元素集合
	 * 用于计算新增或删除的权限 ID
	 * @param main 主集合（通常为“旧权限”）
	 * @param diff 比较集合（通常为“新权限”）
	 * @return 差异列表（存在于 diff 不存在于 main 中）
	 */
	private List<String> getDiff(String main, String diff) {
		if (oConvertUtils.isEmpty(diff)) {
			return null;
		}
		if (oConvertUtils.isEmpty(main)) {
			// 如果 main 为空，全部为新增
			return Arrays.asList(diff.split(","));
		}

		String[] mainArr = main.split(",");
		String[] diffArr = diff.split(",");
		Map<String, Integer> map = new HashMap<>();
		for (String string : mainArr) {
			map.put(string, 1); // 构造主集合映射
		}

		List<String> res = new ArrayList<>();
		for (String key : diffArr) {
			// 过滤掉 main 中已有的 key
			if (oConvertUtils.isNotEmpty(key) && !map.containsKey(key)) {
				res.add(key);
			}
		}
		return res;
	}
}

